# coding=utf-8

from string import Template
from generator.libsomeip.some_ip_type import SomeIP
from utils.payload import TypeEnum

from utils.util import writeFile

templete_read_property_cpp=Template(
"""
#include <someip.pb.h>
#include "PlatformProperty.h"

TRANSMIT_READ_PROPERTY(${properyName},${propType}) {
    builder.area(VehicleArea::GLOBAL)
        .vehiclePropValueCommitMode(${commitMode})
        .initValue([](){
                return ${initValue};
        })
        .immutableStatus(PropertyStatus::Active)
        .withValueBySignals([]([[maybe_unused]]const ${propType}& last){
${impl}
        },ecarx::transfer::SOMEIPRX::${signalName});
}
"""
)

templete_base_type_parse=Template(
"""
            auto signal=SIGNAL.get${signalName}();
            return signal;
"""
)

templete_enum_type_parse=Template(
"""
            auto signal=SIGNAL.get${signalName}();
            return ${propType}((int32_t)signal);
"""
)

templete_array_parse=Template(
"""
            auto signal=SIGNAL.get${signalName}();
            auto value=std::vector<${propType}>{signal.begin(),signal.end()};
            return value;
"""
)

templete_string_parse=Template(
"""
            auto str=SIGNAL.get${signalName}();
            return str;
"""
)

templete_struct_parse=Template(
"""
            auto obj=SIGNAL.get${signalName}();
            proto::someip::${struct_Type} protoObj;
            ${members}
            return protoObj;
"""
)

templete_struct_member_parse=Template(
"""           protoObj.set_${protoMember}(obj.${member});"""
)


def gen_SomeIPReadDirectTransmitProperty(someip:SomeIP):
    for msg in [msg for msg in someip.msg if not msg.isSend()]:
        for item in  [item for item in msg.item if item.isDirectTransmit()]:
            if item.payloadType.value<=9:
                if item.encodeType is not None and item.encodeType.isEnum():
                    writeFile("../vhal_platform/directTransmit", "{}.cpp".format(item.msgName),
                        lambda file: file.write(templete_read_property_cpp.substitute(
                            properyName=item.msgName,
                            propType=item.encodeType.getTypeName(),
                            initValue="{}(-1)".format(item.encodeType.getTypeName()),
                            commitMode="CommitMode::{}".format(item.toNotifyMode()),
                            impl=templete_enum_type_parse.substitute(
                                    signalName=item.msgName,
                                    propType=item.encodeType.getTypeName()
                                ),
                            signalName=item.msgName
                        )))
                else:
                    def to_type(payload_type):
                        if payload_type.value<=6:
                            return "int32_t"
                        elif payload_type.value<=8:
                            return "int64_t"
                        else:
                            return "float"
                    writeFile("../vhal_platform/directTransmit", "{}.cpp".format(item.msgName),
                        lambda file: file.write(templete_read_property_cpp.substitute(
                            properyName=item.msgName,
                            propType=to_type(item.payloadType),
                            initValue="-1",
                            commitMode="CommitMode::{}".format(item.toNotifyMode()),
                            impl=templete_base_type_parse.substitute(
                                    signalName=item.msgName
                                ),
                            signalName=item.msgName
                        )))
            elif item.payloadType.value>=11 and item.payloadType.value<=19:
                def array_type(payload_type):
                    if payload_type==TypeEnum.int8_t_array or payload_type==TypeEnum.uint8_t_array:
                        return "uint8_t"
                    elif payload_type==TypeEnum.int16_t_array or payload_type==TypeEnum.uint16_t_array:
                        return "int32_t"
                    elif payload_type==TypeEnum.int32_t_array or payload_type==TypeEnum.uint32_t_array:
                        return "int32_t"
                    elif payload_type==TypeEnum.int64_t_array or payload_type==TypeEnum.uint64_t_array:
                        return "int64_t"
                    elif payload_type==TypeEnum.float_array:
                        return "float"
                writeFile("../vhal_platform/directTransmit", "{}.cpp".format(item.msgName),
                        lambda file: file.write(templete_read_property_cpp.substitute(
                            properyName=item.msgName,
                            propType="std::vector<{}>".format(array_type(item.payloadType)),
                            initValue="std::vector<{}>{{}}".format(array_type(item.payloadType)),
                            commitMode="CommitMode::{}".format(item.toNotifyMode()),
                            impl=templete_array_parse.substitute(
                                    signalName=item.msgName,
                                    propType=array_type(item.payloadType)
                                ),
                            signalName=item.msgName
                        )))
            elif item.payloadType == TypeEnum.string:
                writeFile("../vhal_platform/directTransmit", "{}.cpp".format(item.msgName),
                        lambda file: file.write(templete_read_property_cpp.substitute(
                            properyName=item.msgName,
                            propType="std::string",
                            initValue="",
                            commitMode="CommitMode::{}".format(item.toNotifyMode()),
                            impl=templete_string_parse.substitute(
                                    signalName=item.msgName
                                ),
                            signalName=item.msgName
                        )))
            elif item.payloadType == TypeEnum.struct_type:
                members=[]
                encodeType = item.encodeType
                for (member,_) in encodeType.members:
                    (_,fieldName)=member.split(" ")
                    members.append(templete_struct_member_parse.substitute(
                        member=fieldName,
                        protoMember = fieldName.lower()

                    ))
                writeFile("../vhal_platform/directTransmit", "{}.cpp".format(item.msgName),
                        lambda file: file.write(templete_read_property_cpp.substitute(
                            properyName=item.msgName,
                            propType="proto::someip::"+item.encodeType.getTypeName(),
                            initValue="{{}}".format(""),
                            commitMode="CommitMode::{}".format(item.toNotifyMode()),
                            impl=templete_struct_parse.substitute(
                                    signalName=item.msgName,
                                    struct_Type=item.encodeType.getTypeName(),
                                    members="\n".join(members)
                                ),
                            signalName=item.msgName
                        )))